#include "HCM/ComponentRegistry.h"
#include "HCM/ComponentFactory.h"

using namespace Hiranipra;
using namespace Hiranipra::HCM;

typedef pair<HCMID, ComponentFactory*> hcmpair;
typedef hcmmap::iterator hcmiterator;
typedef hcmmap::const_iterator hcmiteratorc;
typedef pair<hcmiteratorc, hcmiteratorc> hcmiterators;

void ComponentRegistry::Register( const ComponentFactory* factory )
{
	hcmpair p;
	p.first = factory->TypeID;
	p.second = ( ComponentFactory* )factory;
	_factories.insert( p );
}

vector<const ComponentFactory*> ComponentRegistry::GetFactories( HCMID typeId ) const
{
	vector<const ComponentFactory*> factories;

	hcmiterators iterators = _factories.equal_range( typeId );
	if( iterators.first == iterators.second )
		return factories;

	for( hcmiteratorc it = iterators.first; it != iterators.second; ++it )
		factories.push_back( it->second );

	return factories;
}

IComponent* ComponentRegistry::AllocateDefault( HCMID typeId ) const
{
	hcmiterators iterators = _factories.equal_range( typeId );
	if( iterators.first == iterators.second )
		return NULL;

	for( hcmiteratorc it = iterators.first; it != iterators.second; ++it )
		return it->second->Allocate();

	return NULL;
}

IComponent* ComponentRegistry::Allocate( HCMID typeId, HCMID implId ) const
{
	hcmiterators iterators = _factories.equal_range( typeId );
	if( iterators.first == iterators.second )
		return NULL;

	for( hcmiteratorc it = iterators.first; it != iterators.second; ++it )
	{
		if( Equals( it->second->ImplID, implId ) == true )
		{
			ComponentFactory* factory = ( ComponentFactory* )it->second;
			return factory->Allocate();
		}
	}

	return NULL;
}
